package com.yt.order.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.yt.common.enums.CodeEnum;
import com.yt.common.exception.BusinessException;
import com.yt.order.mapper.*;
import com.yt.order.models.bo.WorkOrderAutoDispatchBO;
import com.yt.order.models.bo.WorkOrderInfoBO;
import com.yt.order.models.dto.*;
import com.yt.order.models.service.IAutoDispatchService;
import com.yt.order.models.vo.DispatchResultVO;
import com.yt.order.models.vo.EmployeeVO;
import com.yt.order.models.vo.WorkOrderInfoVO;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;

/**
 * 自动派单服务实现类
 *
 * @author chen
 * @Date 2025-09-22
 */
@DubboService
@Service
public class AutoDispatchServiceImpl implements IAutoDispatchService {

    @Resource
    private WorkOrderInfoMapper workOrderInfoMapper;

    @Resource
    private DispatchRuleConfigMapper ruleConfigMapper;

    @Resource
    private DispatchRuleFilterMapper ruleFilterMapper;

    @Resource
    private DispatchRuleLogMapper ruleLogMapper;

    @Resource
    private EmployeeMapper employeeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DispatchResultVO executeAutoDispatch(WorkOrderAutoDispatchBO bo) {
        // 1. 初始化结果对象
        DispatchResultVO result = new DispatchResultVO();
        result.setTotalProcessed(0);
        result.setSuccessCount(0);
        result.setFailCount(0);
        result.setDispatchDetails(new ArrayList<>());

        // 2. 获取未派单工单
        List<WorkOrderInfoVO> unassignedOrders = workOrderInfoMapper.selectUnassignedPage(
                new Page<>(1, bo.getBatchSize()), new WorkOrderInfoBO()
        );
        if (unassignedOrders.isEmpty()) {
            result.setMessage("无待派单工单");
            return result;
        }

        // 3. 获取启用的派单规则（按优先级倒序）
        List<DispatchRuleConfigDTO> rules = ruleConfigMapper.selectEnabledRules();
        if (rules.isEmpty()) {
            throw new BusinessException(CodeEnum.FAIL_100011.getCode(), "未配置启用的派单规则");
        }

        for (WorkOrderInfoVO order : unassignedOrders) {
            result.setTotalProcessed(result.getTotalProcessed() + 1);
            try {
                // 4.1 执行派单规则筛选员工（获取候选列表）
                List<EmployeeVO> candidateEmployees = getCandidateEmployees(order, rules, bo.getForceAllRules());
                if (candidateEmployees.isEmpty()) {
                    result.getDispatchDetails().add(
                            String.format("工单ID:%s 派单失败:无符合条件的员工", order.getId())
                    );
                    result.setFailCount(result.getFailCount() + 1);
                    continue;
                }

                // 4.2 遍历候选员工，找到第一个可用的（在途工单<5）
                Long targetEmployeeId = null;
                for (EmployeeVO employee : candidateEmployees) {
                    int currentOrders = employeeMapper.countProcessingOrders(employee.getId());
                    if (currentOrders < 5) { // 小于上限才可用
                        targetEmployeeId = employee.getId();
                        break;
                    }
                }

                if (targetEmployeeId == null) {
                    result.getDispatchDetails().add(
                            String.format("工单ID:%s 派单失败:所有候选员工均已达工单上限", order.getId())
                    );
                    result.setFailCount(result.getFailCount() + 1);
                    continue;
                }

                // 4.3 更新工单信息
                WorkOrderInfoDTO updateDTO = new WorkOrderInfoDTO();
                updateDTO.setId(order.getId());
                updateDTO.setEmployeeId(targetEmployeeId);
                updateDTO.setStatus(1); // 改为进行中
                updateDTO.setUpdateTime(new Date());
                workOrderInfoMapper.updateById(updateDTO);

                // 4.4 记录成功结果
                result.getDispatchDetails().add(
                        String.format("工单ID:%s 派单成功:分配给员工ID=%s", order.getId(), targetEmployeeId)
                );
                result.setSuccessCount(result.getSuccessCount() + 1);
            } catch (Exception e) {
                result.getDispatchDetails().add(
                        String.format("工单ID:%s 处理异常:%s", order.getId(), e.getMessage())
                );
                result.setFailCount(result.getFailCount() + 1);
            }
        }

        result.setMessage("自动派单完成");
        return result;
    }

    /**
     * 按规则筛选员工并派单
     */
    private Long dispatchByRules(WorkOrderInfoVO order, List<DispatchRuleConfigDTO> rules, boolean forceAllRules) {
        // 按规则优先级依次执行
        for (DispatchRuleConfigDTO rule : rules) {
            List<DispatchRuleFilterDTO> filters = ruleFilterMapper.selectByRuleId(rule.getId());
            if (filters.isEmpty()) {
                continue;
            }

            // 根据规则类型筛选员工（不再传递地理位置参数）
            List<EmployeeVO> candidates = filterEmployeesByRule(rule, filters, order);
            DispatchRuleLogDTO log = createDispatchLog(rule, order, candidates);

            // 有符合条件的员工则选择第一个
            if (!candidates.isEmpty()) {
                log.setExecuteResult("成功:找到符合条件的员工");
                ruleLogMapper.insert(log);
                return candidates.get(0).getId();
            }

            // 记录日志
            log.setExecuteResult("失败:无符合条件的员工");
            ruleLogMapper.insert(log);

            // 不强制执行所有规则时，当前规则无结果则直接返回
            if (!forceAllRules) {
                return null;
            }
        }

        return null;
    }

    /**
     * 根据规则类型筛选员工
     */
    private List<EmployeeVO> filterEmployeesByRule(
            DispatchRuleConfigDTO rule,
            List<DispatchRuleFilterDTO> filters,
            WorkOrderInfoVO order) {

        // 2. 服务质量优先规则（ID=2）- 新增排序逻辑
        if (rule.getId().equals(2L)) {
            double minRating = 0;
            int minEvaluation = 0;
            for (DispatchRuleFilterDTO filter : filters) {
                if (filter.getFilterType() == 1 && ">=".equals(filter.getOperator())) {
                    minEvaluation = Integer.parseInt(filter.getFilterVal());
                }
                if (filter.getFilterType() == 2 && ">=".equals(filter.getOperator())) {
                    minRating = Double.parseDouble(filter.getFilterVal());
                }
            }
            // 调用带排序的查询方法
            return employeeMapper.selectByQualityOrdered(minRating, minEvaluation);
        }

        // 3. 负载均衡规则（ID=3）- 强制阈值+修正统计
        if (rule.getId().equals(3L)) {
            // 忽略配置，强制最大在途工单为5
            return employeeMapper.selectByLoadBalance(5);
        }

        return new ArrayList<>();
    }

    /**
     * 创建派单日志
     */
    private DispatchRuleLogDTO createDispatchLog(
            DispatchRuleConfigDTO rule,
            WorkOrderInfoVO order,
            List<EmployeeVO> candidates) {

        DispatchRuleLogDTO log = new DispatchRuleLogDTO();
        log.setId(System.currentTimeMillis());
        log.setRuleId(rule.getId());
        log.setOrderId(order.getId());
        log.setRuleName(rule.getRuleName());
        log.setEmpCount(candidates.size());
        log.setEmpCountFilter(candidates.size());
        log.setFilterDetails(String.format("筛选出%d名符合条件的员工", candidates.size()));
        log.setExecuteTime(new Date());
        return log;
    }

    /**
     * 获取符合规则的候选员工列表
     */
    private List<EmployeeVO> getCandidateEmployees(WorkOrderInfoVO order, List<DispatchRuleConfigDTO> rules, boolean forceAllRules) {
        Long employeeId = dispatchByRules(order, rules, forceAllRules);
        if (employeeId == null) {
            return new ArrayList<>();
        }
        // 构建候选列表
        List<EmployeeVO> candidates = new ArrayList<>();
        EmployeeVO employee = new EmployeeVO();
        employee.setId(employeeId);
        candidates.add(employee);
        return candidates;
    }
}